<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta
    name="viewport"
    content="width=device-width, initial-scale=1.0"
  >
  <title>Virtual Scrolling Example</title>
  <style>
    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }

    #container {
      width: 100%;
      height: 400px;
      overflow-y: auto;
      position: relative;
    }

    .item {
      height: 50px;
      line-height: 50px;
      text-align: center;
      border-bottom: 1px solid #ccc;
    }
  </style>
</head>

<body>
  <div id="container"></div>

  <script>
    // 模拟的数据源  
    const items = new Array(500).fill(0).map((_, x) => x);
    console.log(`a3.html 40 [items]`, items);
    const container = document.getElementById('container');
    const itemHeight = 50; // 每个项目的高度  
    const bufferSize = 3; // 缓冲区大小，即在可视区域外的额外渲染数量  

    let renderedItems = new Set(); // 已渲染的项目集合

    // 渲染函数  
    function render(startIndex, endIndex) {
      for (let i = startIndex; i <= endIndex; i++) {
        if (!renderedItems.has(i)) {
          const item = document.createElement('div');
          item.className = 'item';
          item.textContent = `Item ${i}`;
          container.appendChild(item);
          renderedItems.add(i);
        }
      }
    }

    // 计算可视区域的起始和结束索引  
    function calculateVisibleRange() {
      const scrollTop = container.scrollTop;
      const visibleStartIndex = Math.floor(scrollTop / itemHeight) - bufferSize;
      const visibleEndIndex = Math.min(items.length - 1, Math.floor((scrollTop + container.clientHeight) / itemHeight) + bufferSize);
      return { visibleStartIndex, visibleEndIndex };
    }

    // 滚动事件处理  
    container.addEventListener('scroll', function () {
      const { visibleStartIndex, visibleEndIndex } = calculateVisibleRange();
      render(visibleStartIndex, visibleEndIndex);
    });

    // 初始渲染  
    const { visibleStartIndex, visibleEndIndex } = calculateVisibleRange();
    render(visibleStartIndex, visibleEndIndex);  
  </script>
</body>

</html>